package com.tsing.common.exceptions;

import com.tsing.common.utils.ResultUtil;
import com.tsing.common.vo.BeanValidateExceptionVo;
import com.tsing.common.vo.ResultData;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.conn.HttpHostConnectException;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.UnauthorizedException;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.net.ConnectException;
import java.util.ArrayList;
import java.util.List;

@ControllerAdvice
@RestControllerAdvice
public class FrameExceptionHandlerAdvice {

    private static final Log logger = LogFactory.getLog(FrameExceptionHandlerAdvice.class);

    @ExceptionHandler(Exception.class)
    public ResultData<?> handleException(HttpServletRequest req, HttpServletResponse res, Exception e) {
        logger.error("系统错误", e);
        return ResultUtil.error(600, "系统错误");
    }

    @ExceptionHandler(BusinessException.class)
    public ResultData<?> handleBusinessException(HttpServletRequest req, HttpServletResponse res, BusinessException e) {
        logger.error("系统错误", e);
        return ResultUtil.error(e.getCode(), e.getMessage());
    }

    //form表单参数校验异常
    @ExceptionHandler(BindException.class)
    public ResultData<?> handleBindException(HttpServletRequest req, HttpServletResponse res, BindException e) {
        BindException bException = (BindException) e;
        List<BeanValidateExceptionVo> excepitonVos = new ArrayList<>();
        //解析原错误信息，封装后返回，此处返回非法的字段名称，原始值，错误信息
        for (FieldError error : bException.getBindingResult().getFieldErrors()) {
            BeanValidateExceptionVo excepitonVo = new BeanValidateExceptionVo();
            excepitonVo.setDefaultMessage(error.getDefaultMessage());
            excepitonVo.setField(error.getField());
            excepitonVo.setRejectedValue(error.getRejectedValue());
            excepitonVos.add(excepitonVo);
        }
        return ResultUtil.error(4041, e.getBindingResult().getFieldErrors().get(0).getDefaultMessage(), excepitonVos);
    }

    //json格式参数校验异常
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResultData<?> handleBindException(HttpServletRequest req, HttpServletResponse res, MethodArgumentNotValidException e) {
        List<BeanValidateExceptionVo> excepitonVos = new ArrayList<>();
        //解析原错误信息，封装后返回，此处返回非法的字段名称，原始值，错误信息
        for (FieldError error : e.getBindingResult().getFieldErrors()) {
            BeanValidateExceptionVo excepitonVo = new BeanValidateExceptionVo();
            excepitonVo.setDefaultMessage(error.getDefaultMessage());
            excepitonVo.setField(error.getField());
            excepitonVo.setRejectedValue(error.getRejectedValue());
            excepitonVos.add(excepitonVo);
        }
        return ResultUtil.error(4042, e.getBindingResult().getFieldErrors().get(0).getDefaultMessage(), excepitonVos);
    }

    //拦截未授权页面
    @ExceptionHandler(UnauthorizedException.class)
    public ResultData<?> handleException(UnauthorizedException e) {
        logger.debug(e.getMessage());
        return ResultUtil.error(403, "shiro认证失败");
    }

    @ExceptionHandler(AuthorizationException.class)
    public ResultData<?> handleException2(AuthorizationException e) {
        logger.debug(e.getMessage());
        return ResultUtil.error(403, "您没有权限进行此操作");
    }

    //数据库唯一索引重复添加错误
    @ExceptionHandler(DuplicateKeyException.class)
    public ResultData<?> handleException2(DuplicateKeyException e) {
        logger.debug(e.getMessage());
        return ResultUtil.error(404, "不允许重复添加具有唯一属性的字段");
    }

    @ExceptionHandler(HttpHostConnectException.class)
    public ResultData<?> handleException2(HttpHostConnectException e) {
        logger.debug(e.getMessage());
        return ResultUtil.error(405, "网络连接波动，请稍后再试");
    }

    @ExceptionHandler(ConnectException.class)
    public ResultData<?> handleException2(ConnectException e) {
        logger.debug(e.getMessage());
        return ResultUtil.error(406, "网络连接波动，请稍后再试");
    }

    //oracle数据库非空字段验证
    @ExceptionHandler(DataIntegrityViolationException.class)
    public ResultData<?> dataIntegrityViolationException(DataIntegrityViolationException e) {
        logger.debug(e.getMessage());
        return ResultUtil.error(407, "请传入必填字段");
    }

}
